<?php
class JsonSchemaBuilder {
  
  function __construct() {
  }
  
  public static function schemaFor($data) {
    $j = new JsonSchemaBuilder();
    return json_encode($j->build($data));
  } 
  
  function build($data) {
    $schema = new stdClass();
    switch(gettype($data)) {
      case 'string':
        $schema->type = "string";
        break;
      case 'double':
        $schema->type = "number";
        break;
      case 'integer':
        $schema->type = "integer";
        break;
      case 'boolean':
        $schema->type = "boolean";
        break;
      case 'object':
        $schema->type = "object";
        break;
      case 'array':
        $useObject = false;
        $schema->type = 
          self::isAssociativeArray($data) ?
          "object" :
          "array";
        break;
      case 'NULL':
        $schema->type = 'string';
        break;
      default:
        trigger_error('unknown type:'.gettype($data));  
        break;
    }
    if($schema->type == 'object') {
      $schema->properties = $this->buildProperties($data);
    }
    if($schema->type == 'array') {
      $schema->items = $this->buildItems($data);
    }
    return $schema;
  }
  
  function buildProperties($data) {
    $properties = new stdClass();
    foreach ($data as $name=>$value) {
      $properties->$name = $this->build($value);
    }
    return $properties;
  }
  
  function buildItems($data) {
    return $this->build($data[0]);
  }
  
  static function isAssociativeArray(array $data) {
    $isAssoc = false;
    foreach(array_keys($data) as $key) {
      if(!is_numeric($key)) {
        $isAssoc = true;
          break;
        }
    }
    return $isAssoc;
  }
}
?>